//
// Created by hamlet on 23-6-20.
//

#include "Interpreter.h"
#include <fmt/core.h>

Interpreter::Interpreter(const Sem &sem)
        : idList(sem.idList), valueIntList(sem.valueIntList), quads(sem.quads) {
    idValue.resize(idList.size(), 0);
    tmpValue.resize(sem.curTmpIndex, 0);
}

void Interpreter::execute() {
    static const auto getValue = [this](int i) -> int {
        if (i < (1 << 4)) {
            return idValue[i];
        } else if (i < (1 << 8)) {
            return valueIntList[(i >> 4) - 1];
        } else {
            return tmpValue[(i >> 8) - 1];
        }
    };
    static const auto setValue = [this](int i, int v) -> void {
        if (i < (1 << 4)) {
            idValue[i] = v;
        } else if (i < (1 << 8)) {
        } else {
            tmpValue[(i >> 8) - 1] = v;
        }
    };
    for (int i = 0; i < quads.size(); ++i) {
        const auto &quad = quads[i];
        switch (quad.op) {
            case QuadType::Plus:
                setValue(quad.result, getValue(quad.arg1) + getValue(quad.arg2));
                break;
            case QuadType::Minus:
                setValue(quad.result, getValue(quad.arg1) - getValue(quad.arg2));
                break;
            case QuadType::Multiply:
                setValue(quad.result, getValue(quad.arg1) * getValue(quad.arg2));
                break;
            case QuadType::Divide:
                setValue(quad.result, getValue(quad.arg1) / getValue(quad.arg2));
                break;
            case QuadType::Assign:
                setValue(quad.result, getValue(quad.arg1));
                break;
            case QuadType::J:
                i = quad.result - 1;
                break;
            case QuadType::JEq:
                if (getValue(quad.arg1) == getValue(quad.arg2)) {
                    i = quad.result - 1;
                }
                break;
            case QuadType::JGreater:
                if (getValue(quad.arg1) > getValue(quad.arg2)) {
                    i = quad.result - 1;
                }
                break;
            case QuadType::JLess:
                if (getValue(quad.arg1) < getValue(quad.arg2)) {
                    i = quad.result - 1;
                }
                break;
            case QuadType::JNZ:
                if (getValue(quad.arg1) != 0) {
                    i = quad.result - 1;
                }
                break;
            case QuadType::Print:
                fmt::print("{}\n", getValue(quad.arg1));
                break;
            case QuadType::Start:
                fmt::print("开始执行程序{}：\n", idList[quad.arg1]);
                break;
            case QuadType::Exit:
                fmt::print("进程已结束，退出代码{}\n", getValue(quad.arg1));
                break;
        }
    }
}
